{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor\n",
    "from sklearn.metrics import mean_squared_error\n",
    "from sklearn.preprocessing import StandardScaler, RobustScaler\n",
    "from sklearn.linear_model import Lasso\n",
    "from scipy.stats import uniform, randint\n",
    "from sklearn.model_selection import RandomizedSearchCV, TimeSeriesSplit\n",
    "from sklearn.metrics import make_scorer\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Load the dataset\n",
    "data = pd.read_csv(\"A1_stock_volatility_labeled.csv\")\n",
    "\n",
    "# Convert Date to datetime and sort by date\n",
    "data['Date'] = pd.to_datetime(data['Date'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "stock_df = data.copy()\n",
    "\n",
    "# Extract features from Date\n",
    "stock_df['Year'] = stock_df['Date'].dt.year\n",
    "stock_df['Month'] = stock_df['Date'].dt.month\n",
    "stock_df['DayOfWeek'] = stock_df['Date'].dt.dayofweek\n",
    "\n",
    "stock_df = stock_df.drop('Date', axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Feature Engineering\n",
    "stock_df['Volume_Price_Interaction'] = stock_df['Volume'] * stock_df['Return']\n",
    "stock_df['Price_Range'] = (stock_df['High'] - stock_df['Low']) / stock_df['Open'] * 100\n",
    "stock_df['Volatility_Next'] = stock_df.groupby('Stock')['Volatility'].shift(-1)\n",
    "\n",
    "# Lagged features\n",
    "stock_df['Volatility_Lag1'] = stock_df.groupby('Stock')['Volatility'].shift(1)\n",
    "stock_df['Return_Lag1'] = stock_df.groupby('Stock')['Return'].shift(1)\n",
    "\n",
    "# Rolling statistics: 3-period rolling mean and standard deviation for 'Volatility'\n",
    "stock_df['Volatility_RollingMean'] = stock_df.groupby('Stock')['Volatility'].transform(lambda x: x.rolling(window=3).mean())\n",
    "stock_df['Volatility_RollingStd'] = stock_df.groupby('Stock')['Volatility'].transform(lambda x: x.rolling(window=3).std())\n",
    "\n",
    "# Example: Add technical indicators (e.g., moving averages)\n",
    "stock_df['SMA_5'] = stock_df.groupby('Stock')['Volatility'].transform(lambda x: x.rolling(window=5).mean())\n",
    "\n",
    "# Drop rows with NaN values resulting from lag and rolling operations\n",
    "stock_df = stock_df.dropna()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "num_features = ['Open', 'Close', 'High', 'Low', 'Volume', 'Amount', 'Avg_Price',\n",
    "       'Return', 'Revenue', 'Net Income', 'Gross Profit', 'EPS',\n",
    "       'Total Assets', 'Total Liabilities', 'Total Equity',\n",
    "       'Cash and Cash Equivalents', 'Operating Cash Flow',\n",
    "       'Investing Cash Flow', 'Financing Cash Flow',\n",
    "       'Volume_Price_Interaction', 'Volatility_Lag1',\n",
    "       'Return_Lag1', 'Volatility_RollingMean', 'Volatility_RollingStd',\n",
    "       'SMA_5']\n",
    "\n",
    "# Initialize the scaler\n",
    "scaler = RobustScaler()\n",
    "\n",
    "# Fit and transform the numerical features\n",
    "stock_df[num_features] = scaler.fit_transform(stock_df[num_features])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Select features and target\n",
    "features = ['Volatility_RollingMean', 'SMA_5', 'Volatility_Lag1',\n",
    "            'Volatility_RollingStd', 'Return', 'DayOfWeek', 'Volume_Price_Interaction',\n",
    "            'Volume', 'Return_Lag1', 'Price_Range', 'Month']\n",
    "target = 'Volatility_Next'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Split the data into training and validation sets \n",
    "train_set = stock_df.groupby('Stock').apply(lambda x: x.iloc[:-4]).reset_index(drop=True)\n",
    "validation_set = stock_df.groupby('Stock').apply(lambda x: x.iloc[-4:]).reset_index(drop=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Separate features and target for training and testing\n",
    "X_train = train_set[features]\n",
    "y_train = train_set[target]\n",
    "X_test = validation_set[features]\n",
    "y_test = validation_set[target]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "----\n",
    "Randomforest Model Training and Tuning Hyperparameter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-1 {color: black;background-color: white;}#sk-container-id-1 pre{padding: 0;}#sk-container-id-1 div.sk-toggleable {background-color: white;}#sk-container-id-1 label.sk-toggleable__label {cursor: pointer;display: block;width: 100%;margin-bottom: 0;padding: 0.3em;box-sizing: border-box;text-align: center;}#sk-container-id-1 label.sk-toggleable__label-arrow:before {content: \"▸\";float: left;margin-right: 0.25em;color: #696969;}#sk-container-id-1 label.sk-toggleable__label-arrow:hover:before {color: black;}#sk-container-id-1 div.sk-estimator:hover label.sk-toggleable__label-arrow:before {color: black;}#sk-container-id-1 div.sk-toggleable__content {max-height: 0;max-width: 0;overflow: hidden;text-align: left;background-color: #f0f8ff;}#sk-container-id-1 div.sk-toggleable__content pre {margin: 0.2em;color: black;border-radius: 0.25em;background-color: #f0f8ff;}#sk-container-id-1 input.sk-toggleable__control:checked~div.sk-toggleable__content {max-height: 200px;max-width: 100%;overflow: auto;}#sk-container-id-1 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {content: \"▾\";}#sk-container-id-1 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-1 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-1 input.sk-hidden--visually {border: 0;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);height: 1px;margin: -1px;overflow: hidden;padding: 0;position: absolute;width: 1px;}#sk-container-id-1 div.sk-estimator {font-family: monospace;background-color: #f0f8ff;border: 1px dotted black;border-radius: 0.25em;box-sizing: border-box;margin-bottom: 0.5em;}#sk-container-id-1 div.sk-estimator:hover {background-color: #d4ebff;}#sk-container-id-1 div.sk-parallel-item::after {content: \"\";width: 100%;border-bottom: 1px solid gray;flex-grow: 1;}#sk-container-id-1 div.sk-label:hover label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-1 div.sk-serial::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: 0;}#sk-container-id-1 div.sk-serial {display: flex;flex-direction: column;align-items: center;background-color: white;padding-right: 0.2em;padding-left: 0.2em;position: relative;}#sk-container-id-1 div.sk-item {position: relative;z-index: 1;}#sk-container-id-1 div.sk-parallel {display: flex;align-items: stretch;justify-content: center;background-color: white;position: relative;}#sk-container-id-1 div.sk-item::before, #sk-container-id-1 div.sk-parallel-item::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: -1;}#sk-container-id-1 div.sk-parallel-item {display: flex;flex-direction: column;z-index: 1;position: relative;background-color: white;}#sk-container-id-1 div.sk-parallel-item:first-child::after {align-self: flex-end;width: 50%;}#sk-container-id-1 div.sk-parallel-item:last-child::after {align-self: flex-start;width: 50%;}#sk-container-id-1 div.sk-parallel-item:only-child::after {width: 0;}#sk-container-id-1 div.sk-dashed-wrapped {border: 1px dashed gray;margin: 0 0.4em 0.5em 0.4em;box-sizing: border-box;padding-bottom: 0.4em;background-color: white;}#sk-container-id-1 div.sk-label label {font-family: monospace;font-weight: bold;display: inline-block;line-height: 1.2em;}#sk-container-id-1 div.sk-label-container {text-align: center;}#sk-container-id-1 div.sk-container {/* jupyter's `normalize.less` sets `[hidden] { display: none; }` but bootstrap.min.css set `[hidden] { display: none !important; }` so we also need the `!important` here to be able to override the default hidden behavior on the sphinx rendered scikit-learn.org. See: https://github.com/scikit-learn/scikit-learn/issues/21755 */display: inline-block !important;position: relative;}#sk-container-id-1 div.sk-text-repr-fallback {display: none;}</style><div id=\"sk-container-id-1\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>RandomForestRegressor(random_state=1)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-1\" type=\"checkbox\" checked><label for=\"sk-estimator-id-1\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">RandomForestRegressor</label><div class=\"sk-toggleable__content\"><pre>RandomForestRegressor(random_state=1)</pre></div></div></div></div></div>"
      ],
      "text/plain": [
       "RandomForestRegressor(random_state=1)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rf_model = RandomForestRegressor(random_state=1)\n",
    "rf_model.fit(X_train, y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "                     Feature  Importance\n",
      "1                      SMA_5    0.360099\n",
      "0     Volatility_RollingMean    0.274681\n",
      "9                Price_Range    0.092931\n",
      "4                     Return    0.070345\n",
      "8                Return_Lag1    0.041287\n",
      "7                     Volume    0.039314\n",
      "3      Volatility_RollingStd    0.033410\n",
      "2            Volatility_Lag1    0.032541\n",
      "6   Volume_Price_Interaction    0.021651\n",
      "5                  DayOfWeek    0.020845\n",
      "10                     Month    0.012896\n"
     ]
    },
    {
     "data": {
      "image/png": "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2GN68cUXtW7duhvu6/jx4+Xt7W2dAgICzB4uAAAAAPexOyZMBwcHKzw8XHFxcZKujjZ+++23io2N1f79+9WkSROb9k2aNNHBgweVnZ2db38bNmxQy5YtVaFCBXl6eqpr1646c+aMMjIyin1fevXqpbVr1+q3336TdPVW5piYGFkslpta39PTU8nJydqxY4fmzp2ratWqae7cudblt3I8bka9evWsf/b395cknTp1StLV0fdGjRrZtL/+cy5HR0e98MILio+P19KlSxUUFGTTtyT9/vvvOn78uHr06CEPDw/rNGbMGB06dMja7rPPPtOjjz5q/QePoUOH6tixYzZ9BQYGytPT06b23LoLMnjwYKWlpVmn48eP37A9AAAAAFyreN+kZVKPHj3Uu3dvvf/++4qPj1flypXVvHlzGYaRJ4heezv49Y4ePapWrVrplVde0ejRo1WmTBlt3rxZPXr0sHnetrg0aNBA9evX14cffqioqCjt2bNHn3/++U2vb2dnp+rVq0u6+o8MJ0+eVMeOHfXNN99IkunjcbNybyOXZO0/Jycnz7yb2WZsbKwefvhh7d27N99R6dx+58+fr4cffthmmb29vSTp+++/V6dOnTRy5EhFRUXJ29tbixcvzvN8+LV159Z5bd35cXZ2lrOz8w3bAAAAAEBB7piRaUnq0KGD7O3ttWjRIiUmJqp79+6yWCyqXbu2Nm/ebNM2KSlJQUFB1uB1re3bt+vKlSuaOnWqHnnkEQUFBenEiRM2bZycnAo1ipvbh6R8++nZs6fi4+MVFxenFi1aFOo24n79+mn37t3617/+JUmmj0dRqFmzpn744Qebedu3by+wfZ06dVSnTh3t3btXnTt3zrO8XLlyqlChgg4fPqzq1avbTFWqVJEkfffdd6pcubLeeecdNWzYUDVq1Mj3je8AAAAAcLvdUWHaw8NDHTt21Ntvv60TJ04oJiZGkjRgwACtW7dOo0eP1oEDB5SYmKhZs2YV+NKwatWq6cqVK5o5c6YOHz6shQsX2twmLV29NfjChQtat26dTp8+rYsXL5qut3LlyrJYLFq1apV+//1369vCJalLly767bffNH/+/HxHZs3w8vJSz549NXz4cBmGYfp4FIU+ffpowYIFSkxM1MGDBzVmzBj9+OOPN7x1ff369UpNTc3397ylq2/iHj9+vN577z0dOHBA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VatWycPDQ9nZ2bp06ZIkadq0aZKk0aNHa+rUqWrXrp2kqyPR+/bt07x589StWzeVLVtWkuTj43NLo7TNmjWzCcqbN29WVlaW5s6dq2rVqkmSevfurVGjRhVqH3PFxsZa/1y1alXNmDFDjRo10oULF+Th4aG5c+eqZs2amjx5siSpZs2a2rt3r8aOHVvobY8fP14jR44sdD8AAAAA7k+MTN9hIiMjlZycrK1bt6pPnz6KiopSnz599Pvvv+v48ePq0aOHPDw8rNOYMWN06NChItl2w4YN88xzc3OzBmlJ8vf3z3Mr9q3atWuXnn76aVWuXFmenp7W29KPHTsmSfr555/10EMP2azTqFGjItn24MGDlZaWZp2OHz9eJP0CAAAAuD8wMn2HcXd3V/Xq1SVJM2bMUGRkpEaOHKnevXtLunqr98MPP2yzjr29/Q37tLOzk2EYNvOysrLy3fb1cm8xz2WxWPL0dSsyMjL0xBNP6IknntBHH32ksmXL6tixY4qKirK+/MwwDFksFpv1imLb0tVn052dnYukLwAAAAD3H0am73DDhw/XlClTlJ2drQoVKujw4cOqXr26zZT74jEnJydJV99wfa2yZcvavDQsOztbe/fuvX07kY///ve/On36tCZMmKDHHntMwcHBeUa8g4ODtW3bNpt527dvv51lAgAAAEC+GJm+wzVt2lR16tTRuHHjNGLECL3++uvy8vLSU089pczMTG3fvl1nz55V//795evrK1dXV61evVoVK1aUi4uLvL291axZM/Xv319ffPGFqlWrpnfffdf6Nuzi9ueff+b53WsPDw9VqlRJTk5Omjlzpl555RXt3btXo0ePtmn38ssva9q0aXrrrbfUo0cPJScnKyEhQZJsRqz37duny5cv648//tD58+et2yvu37gGAAAAcP9iZPou0L9/f82fP19RUVH64IMPlJCQoLp16yoiIkIJCQnWkWkHBwfNmDFD8+bNU/ny5fX0009Luvqir27duqlr166KiIhQlSpVFBkZeVtqP3DggBo0aGAz9ezZU2XLllVCQoKWLl2q2rVra8KECZoyZYrNulWqVNFnn32m5cuXq169epozZ471bd7X3qLdqlUrNWjQQJ9//rk2btxo3Q4AAAAAFBeLUVQPoQK3wdixYzV37twif2FYenq6vL29FdB3ieyc3Yq07/tVyoTo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XbpUly9fVuPGjdWhQwd16tRJe/bs0YgRIzR06NA84ftWjBgxQrNmzVJSUpKOHz+uDh06aPr06Vq0aJG++OIL/ec//9HMmTOt7YcMGaL4+HjNmTNHP/30k/r166cXXnjhL2/VLoibm5sk21HZ4cOH6+mnn9aePXsUGxubZ53k5GQ1b95cderU0ZYtW7R582a1adNG2dnZxVKjJL3zzjuaOnWqtm/fLgcHB2tdHTt21IABA1SnTh2lpqYqNTVVHTt2lGEYio6O1smTJ/Xll19qx44dCgsLU/PmzfXHH39Y+/3ll1+0ZMkSLVu2zPqPHxkZGerfv7+2bdumdevWyc7OTs8884xycnIkSRcuXFBERIROnDihlStXavfu3XrzzTeVk5NTYD3Xu3jxop588kmVLl1a27Zt09KlS/X111+rd+/eNu02bNigQ4cOacOGDUpMTFRCQsJffu/Gjx8vb29v6xQQEHDLxx0AAADA/cfBTOPY2FhNnjxZGzduVGRkpKSrt3i3a9dO06ZNU/PmzTV06FBJUlBQkPbt26fJkycrJiamUEWOGTNGTZo0kXT1dvPBgwfr0KFDqlq1qiTp2Wef1YYNG/TWW28pIyND06ZN0/r169W4cWNJUtWqVbV582bNmzdPERERpradkZGhwYMHy97e3mbdzp0724To628BnzRpkho2bKjZs2db59WpU8faZ1HWmGvs2LHWdQcNGqTo6GhdunRJrq6u8vDwkIODg/z8/Kzt169frz179ujUqVPWW6unTJmiFStW6LPPPtNLL70kSbp8+bIWLlyosmXLWtdt3769zbYXLFggX19f7du3TyEhIVq0aJF+//13bdu2TWXKlJEkVa9e3do+v3qu9/HHH+vPP//Uhx9+KHd3d0nSrFmz1KZNG02cOFHlypWTJJUuXVqzZs2Svb29goODFR0drXXr1qlXr14F9j148GD179/f+jk9PZ1ADQAAAOCmmXqbd3BwsMLDwxUXFydJOnTokL799lvFxsZq//791sCbq0mTJjp48KB1NPZW1atXz/rncuXKyc3NzRqkc+edOnVKkrRv3z5dunRJLVu2lIeHh3X68MMP89yGfCPh4eHy8PCQp6enPv/8cyUkJKhu3brW5Q0bNrzh+rkj0/kpqhqvd+1x8vf3lyTrccnPjh07dOHCBfn4+NjUceTIEZs6KleubBOk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",
      "text/plain": [
       "<Figure size 1000x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Get feature importances\n",
    "importances = rf_model.feature_importances_\n",
    "\n",
    "# Create a DataFrame for better visualization\n",
    "feature_names = X_train.columns  # Assuming X_train is a DataFrame\n",
    "importance_df = pd.DataFrame({'Feature': feature_names, 'Importance': importances})\n",
    "importance_df = importance_df.sort_values(by='Importance', ascending=False)\n",
    "print(importance_df)\n",
    "\n",
    "# Plot feature importances\n",
    "plt.figure(figsize=(10, 6))\n",
    "plt.barh(importance_df['Feature'], importance_df['Importance'])\n",
    "plt.xlabel('Importance')\n",
    "plt.title('Feature Importances - RandomForest')\n",
    "plt.gca().invert_yaxis()  # Invert y-axis to have the most important features on top\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "param_distributions = {\n",
    "        'n_estimators': randint(50, 200),\n",
    "        'max_depth': randint(10, 30),\n",
    "        'min_samples_split': randint(2, 10),\n",
    "        'min_samples_leaf': randint(1, 4),\n",
    "        'max_features': ['sqrt', 'log2']\n",
    "    }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define RMSE as the scoring metric\n",
    "rmse_scorer = make_scorer(mean_squared_error, squared=False)\n",
    "\n",
    "# Time series cross-validation\n",
    "tscv = TimeSeriesSplit(n_splits=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-2 {color: black;background-color: white;}#sk-container-id-2 pre{padding: 0;}#sk-container-id-2 div.sk-toggleable {background-color: white;}#sk-container-id-2 label.sk-toggleable__label {cursor: pointer;display: block;width: 100%;margin-bottom: 0;padding: 0.3em;box-sizing: border-box;text-align: center;}#sk-container-id-2 label.sk-toggleable__label-arrow:before {content: \"▸\";float: left;margin-right: 0.25em;color: #696969;}#sk-container-id-2 label.sk-toggleable__label-arrow:hover:before {color: black;}#sk-container-id-2 div.sk-estimator:hover label.sk-toggleable__label-arrow:before {color: black;}#sk-container-id-2 div.sk-toggleable__content {max-height: 0;max-width: 0;overflow: hidden;text-align: left;background-color: #f0f8ff;}#sk-container-id-2 div.sk-toggleable__content pre {margin: 0.2em;color: black;border-radius: 0.25em;background-color: #f0f8ff;}#sk-container-id-2 input.sk-toggleable__control:checked~div.sk-toggleable__content {max-height: 200px;max-width: 100%;overflow: auto;}#sk-container-id-2 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {content: \"▾\";}#sk-container-id-2 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-2 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-2 input.sk-hidden--visually {border: 0;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);height: 1px;margin: -1px;overflow: hidden;padding: 0;position: absolute;width: 1px;}#sk-container-id-2 div.sk-estimator {font-family: monospace;background-color: #f0f8ff;border: 1px dotted black;border-radius: 0.25em;box-sizing: border-box;margin-bottom: 0.5em;}#sk-container-id-2 div.sk-estimator:hover {background-color: #d4ebff;}#sk-container-id-2 div.sk-parallel-item::after {content: \"\";width: 100%;border-bottom: 1px solid gray;flex-grow: 1;}#sk-container-id-2 div.sk-label:hover label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-2 div.sk-serial::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: 0;}#sk-container-id-2 div.sk-serial {display: flex;flex-direction: column;align-items: center;background-color: white;padding-right: 0.2em;padding-left: 0.2em;position: relative;}#sk-container-id-2 div.sk-item {position: relative;z-index: 1;}#sk-container-id-2 div.sk-parallel {display: flex;align-items: stretch;justify-content: center;background-color: white;position: relative;}#sk-container-id-2 div.sk-item::before, #sk-container-id-2 div.sk-parallel-item::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: -1;}#sk-container-id-2 div.sk-parallel-item {display: flex;flex-direction: column;z-index: 1;position: relative;background-color: white;}#sk-container-id-2 div.sk-parallel-item:first-child::after {align-self: flex-end;width: 50%;}#sk-container-id-2 div.sk-parallel-item:last-child::after {align-self: flex-start;width: 50%;}#sk-container-id-2 div.sk-parallel-item:only-child::after {width: 0;}#sk-container-id-2 div.sk-dashed-wrapped {border: 1px dashed gray;margin: 0 0.4em 0.5em 0.4em;box-sizing: border-box;padding-bottom: 0.4em;background-color: white;}#sk-container-id-2 div.sk-label label {font-family: monospace;font-weight: bold;display: inline-block;line-height: 1.2em;}#sk-container-id-2 div.sk-label-container {text-align: center;}#sk-container-id-2 div.sk-container {/* jupyter's `normalize.less` sets `[hidden] { display: none; }` but bootstrap.min.css set `[hidden] { display: none !important; }` so we also need the `!important` here to be able to override the default hidden behavior on the sphinx rendered scikit-learn.org. See: https://github.com/scikit-learn/scikit-learn/issues/21755 */display: inline-block !important;position: relative;}#sk-container-id-2 div.sk-text-repr-fallback {display: none;}</style><div id=\"sk-container-id-2\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>RandomizedSearchCV(cv=TimeSeriesSplit(gap=0, max_train_size=None, n_splits=5, test_size=None),\n",
       "                   estimator=RandomForestRegressor(random_state=1), n_jobs=-1,\n",
       "                   param_distributions={&#x27;max_depth&#x27;: &lt;scipy.stats._distn_infrastructure.rv_discrete_frozen object at 0x16bb31990&gt;,\n",
       "                                        &#x27;max_features&#x27;: [&#x27;sqrt&#x27;, &#x27;log2&#x27;],\n",
       "                                        &#x27;min_samples_leaf&#x27;: &lt;scipy.stats._distn_infrastructure.rv_discrete_frozen object at 0x16b4ff990&gt;,\n",
       "                                        &#x27;min_samples_split&#x27;: &lt;scipy.stats._distn_infrastructure.rv_discrete_frozen object at 0x16baa2a50&gt;,\n",
       "                                        &#x27;n_estimators&#x27;: &lt;scipy.stats._distn_infrastructure.rv_discrete_frozen object at 0x16bb3e950&gt;},\n",
       "                   random_state=1,\n",
       "                   scoring=make_scorer(mean_squared_error, squared=False))</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item sk-dashed-wrapped\"><div class=\"sk-label-container\"><div class=\"sk-label sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-2\" type=\"checkbox\" ><label for=\"sk-estimator-id-2\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">RandomizedSearchCV</label><div class=\"sk-toggleable__content\"><pre>RandomizedSearchCV(cv=TimeSeriesSplit(gap=0, max_train_size=None, n_splits=5, test_size=None),\n",
       "                   estimator=RandomForestRegressor(random_state=1), n_jobs=-1,\n",
       "                   param_distributions={&#x27;max_depth&#x27;: &lt;scipy.stats._distn_infrastructure.rv_discrete_frozen object at 0x16bb31990&gt;,\n",
       "                                        &#x27;max_features&#x27;: [&#x27;sqrt&#x27;, &#x27;log2&#x27;],\n",
       "                                        &#x27;min_samples_leaf&#x27;: &lt;scipy.stats._distn_infrastructure.rv_discrete_frozen object at 0x16b4ff990&gt;,\n",
       "                                        &#x27;min_samples_split&#x27;: &lt;scipy.stats._distn_infrastructure.rv_discrete_frozen object at 0x16baa2a50&gt;,\n",
       "                                        &#x27;n_estimators&#x27;: &lt;scipy.stats._distn_infrastructure.rv_discrete_frozen object at 0x16bb3e950&gt;},\n",
       "                   random_state=1,\n",
       "                   scoring=make_scorer(mean_squared_error, squared=False))</pre></div></div></div><div class=\"sk-parallel\"><div class=\"sk-parallel-item\"><div class=\"sk-item\"><div class=\"sk-label-container\"><div class=\"sk-label sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-3\" type=\"checkbox\" ><label for=\"sk-estimator-id-3\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">estimator: RandomForestRegressor</label><div class=\"sk-toggleable__content\"><pre>RandomForestRegressor(random_state=1)</pre></div></div></div><div class=\"sk-serial\"><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-4\" type=\"checkbox\" ><label for=\"sk-estimator-id-4\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">RandomForestRegressor</label><div class=\"sk-toggleable__content\"><pre>RandomForestRegressor(random_state=1)</pre></div></div></div></div></div></div></div></div></div></div>"
      ],
      "text/plain": [
       "RandomizedSearchCV(cv=TimeSeriesSplit(gap=0, max_train_size=None, n_splits=5, test_size=None),\n",
       "                   estimator=RandomForestRegressor(random_state=1), n_jobs=-1,\n",
       "                   param_distributions={'max_depth': <scipy.stats._distn_infrastructure.rv_discrete_frozen object at 0x16bb31990>,\n",
       "                                        'max_features': ['sqrt', 'log2'],\n",
       "                                        'min_samples_leaf': <scipy.stats._distn_infrastructure.rv_discrete_frozen object at 0x16b4ff990>,\n",
       "                                        'min_samples_split': <scipy.stats._distn_infrastructure.rv_discrete_frozen object at 0x16baa2a50>,\n",
       "                                        'n_estimators': <scipy.stats._distn_infrastructure.rv_discrete_frozen object at 0x16bb3e950>},\n",
       "                   random_state=1,\n",
       "                   scoring=make_scorer(mean_squared_error, squared=False))"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "random_search = RandomizedSearchCV(estimator=rf_model, param_distributions=param_distributions, \n",
    "                                    scoring=rmse_scorer, cv=tscv, n_jobs=-1, random_state=1)\n",
    "random_search.fit(X_train, y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Best RF RMSE: 1.6113\n",
      "Best RF Params: {'max_depth': 17, 'max_features': 'log2', 'min_samples_leaf': 3, 'min_samples_split': 7, 'n_estimators': 99}\n"
     ]
    }
   ],
   "source": [
    "# Best RF model\n",
    "best_rf = random_search.best_estimator_\n",
    "print(f\"Best RF RMSE: {random_search.best_score_:.4f}\")\n",
    "print(f\"Best RF Params: {random_search.best_params_}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "RMSE (RF): 0.975815191696332\n"
     ]
    }
   ],
   "source": [
    "rf_pred = best_rf.predict(X_test)\n",
    "\n",
    "rf_pd = pd.DataFrame({\n",
    "    'Stock': validation_set['Stock'],\n",
    "    'Volatility' : y_test,\n",
    "    'Volatility_P': rf_pred\n",
    "})\n",
    "\n",
    "\n",
    "rmse = np.sqrt(mean_squared_error(y_test, rf_pred))\n",
    "print(\"RMSE (RF):\", rmse)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "----\n",
    "Forecasting 23rd Month"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "stock_df = data.copy()\n",
    "\n",
    "# Extract features from Date\n",
    "stock_df['Year'] = stock_df['Date'].dt.year\n",
    "stock_df['Month'] = stock_df['Date'].dt.month\n",
    "stock_df['DayOfWeek'] = stock_df['Date'].dt.dayofweek\n",
    "\n",
    "stock_df = stock_df.drop('Date', axis=1)\n",
    "\n",
    "# Feature Engineering\n",
    "stock_df['Volume_Price_Interaction'] = stock_df['Volume'] * stock_df['Return']\n",
    "stock_df['Price_Range'] = (stock_df['High'] - stock_df['Low']) / stock_df['Open'] * 100\n",
    "\n",
    "# Lagged features\n",
    "stock_df['Volatility_Lag1'] = stock_df.groupby('Stock')['Volatility'].shift(1)\n",
    "stock_df['Return_Lag1'] = stock_df.groupby('Stock')['Return'].shift(1)\n",
    "\n",
    "# Rolling statistics: 3-period rolling mean and standard deviation for 'Volatility'\n",
    "stock_df['Volatility_RollingMean'] = stock_df.groupby('Stock')['Volatility'].transform(lambda x: x.rolling(window=3).mean())\n",
    "stock_df['Volatility_RollingStd'] = stock_df.groupby('Stock')['Volatility'].transform(lambda x: x.rolling(window=3).std())\n",
    "\n",
    "# Example: Add technical indicators (e.g., moving averages)\n",
    "stock_df['SMA_5'] = stock_df.groupby('Stock')['Volatility'].transform(lambda x: x.rolling(window=5).mean())\n",
    "\n",
    "# Drop rows with NaN values resulting from lag and rolling operations\n",
    "stock_df = stock_df.dropna()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "stock_df['Volatility_Next'] = stock_df.groupby('Stock')['Volatility'].shift(-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "num_features = ['Open', 'Close', 'High', 'Low', 'Volume', 'Amount', 'Avg_Price',\n",
    "       'Return', 'Revenue', 'Net Income', 'Gross Profit', 'EPS',\n",
    "       'Total Assets', 'Total Liabilities', 'Total Equity',\n",
    "       'Cash and Cash Equivalents', 'Operating Cash Flow',\n",
    "       'Investing Cash Flow', 'Financing Cash Flow',\n",
    "       'Volume_Price_Interaction', 'Volatility_Lag1',\n",
    "       'Return_Lag1', 'Volatility_RollingMean', 'Volatility_RollingStd',\n",
    "       'SMA_5']\n",
    "\n",
    "# Initialize the scaler\n",
    "scaler = RobustScaler()\n",
    "\n",
    "# Fit and transform the numerical features\n",
    "stock_df[num_features] = scaler.fit_transform(stock_df[num_features])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "stock_forecast = stock_df.copy()\n",
    "\n",
    "# Split the data into training and test sets\n",
    "train_set = stock_forecast.groupby('Stock').apply(lambda x: x.iloc[:-1]).reset_index(drop=True)\n",
    "test_set = stock_forecast.groupby('Stock').apply(lambda x: x.iloc[-1:]).reset_index(drop=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Select features and target\n",
    "features = ['Volatility_RollingMean', 'SMA_5', 'Volatility_Lag1',\n",
    "            'Volatility_RollingStd', 'Return', 'DayOfWeek', 'Volume_Price_Interaction',\n",
    "            'Volume', 'Return_Lag1', 'Price_Range', 'Month']\n",
    "target = 'Volatility_Next'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Separate features and target for training and testing\n",
    "X_train = train_set[features]\n",
    "y_train = train_set[target]\n",
    "X_test = test_set[features]\n",
    "y_test = test_set[target]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-3 {color: black;background-color: white;}#sk-container-id-3 pre{padding: 0;}#sk-container-id-3 div.sk-toggleable {background-color: white;}#sk-container-id-3 label.sk-toggleable__label {cursor: pointer;display: block;width: 100%;margin-bottom: 0;padding: 0.3em;box-sizing: border-box;text-align: center;}#sk-container-id-3 label.sk-toggleable__label-arrow:before {content: \"▸\";float: left;margin-right: 0.25em;color: #696969;}#sk-container-id-3 label.sk-toggleable__label-arrow:hover:before {color: black;}#sk-container-id-3 div.sk-estimator:hover label.sk-toggleable__label-arrow:before {color: black;}#sk-container-id-3 div.sk-toggleable__content {max-height: 0;max-width: 0;overflow: hidden;text-align: left;background-color: #f0f8ff;}#sk-container-id-3 div.sk-toggleable__content pre {margin: 0.2em;color: black;border-radius: 0.25em;background-color: #f0f8ff;}#sk-container-id-3 input.sk-toggleable__control:checked~div.sk-toggleable__content {max-height: 200px;max-width: 100%;overflow: auto;}#sk-container-id-3 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {content: \"▾\";}#sk-container-id-3 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-3 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-3 input.sk-hidden--visually {border: 0;clip: rect(1px 1px 1px 1px);clip: rect(1px, 1px, 1px, 1px);height: 1px;margin: -1px;overflow: hidden;padding: 0;position: absolute;width: 1px;}#sk-container-id-3 div.sk-estimator {font-family: monospace;background-color: #f0f8ff;border: 1px dotted black;border-radius: 0.25em;box-sizing: border-box;margin-bottom: 0.5em;}#sk-container-id-3 div.sk-estimator:hover {background-color: #d4ebff;}#sk-container-id-3 div.sk-parallel-item::after {content: \"\";width: 100%;border-bottom: 1px solid gray;flex-grow: 1;}#sk-container-id-3 div.sk-label:hover label.sk-toggleable__label {background-color: #d4ebff;}#sk-container-id-3 div.sk-serial::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: 0;}#sk-container-id-3 div.sk-serial {display: flex;flex-direction: column;align-items: center;background-color: white;padding-right: 0.2em;padding-left: 0.2em;position: relative;}#sk-container-id-3 div.sk-item {position: relative;z-index: 1;}#sk-container-id-3 div.sk-parallel {display: flex;align-items: stretch;justify-content: center;background-color: white;position: relative;}#sk-container-id-3 div.sk-item::before, #sk-container-id-3 div.sk-parallel-item::before {content: \"\";position: absolute;border-left: 1px solid gray;box-sizing: border-box;top: 0;bottom: 0;left: 50%;z-index: -1;}#sk-container-id-3 div.sk-parallel-item {display: flex;flex-direction: column;z-index: 1;position: relative;background-color: white;}#sk-container-id-3 div.sk-parallel-item:first-child::after {align-self: flex-end;width: 50%;}#sk-container-id-3 div.sk-parallel-item:last-child::after {align-self: flex-start;width: 50%;}#sk-container-id-3 div.sk-parallel-item:only-child::after {width: 0;}#sk-container-id-3 div.sk-dashed-wrapped {border: 1px dashed gray;margin: 0 0.4em 0.5em 0.4em;box-sizing: border-box;padding-bottom: 0.4em;background-color: white;}#sk-container-id-3 div.sk-label label {font-family: monospace;font-weight: bold;display: inline-block;line-height: 1.2em;}#sk-container-id-3 div.sk-label-container {text-align: center;}#sk-container-id-3 div.sk-container {/* jupyter's `normalize.less` sets `[hidden] { display: none; }` but bootstrap.min.css set `[hidden] { display: none !important; }` so we also need the `!important` here to be able to override the default hidden behavior on the sphinx rendered scikit-learn.org. See: https://github.com/scikit-learn/scikit-learn/issues/21755 */display: inline-block !important;position: relative;}#sk-container-id-3 div.sk-text-repr-fallback {display: none;}</style><div id=\"sk-container-id-3\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>RandomForestRegressor(max_depth=17, max_features=&#x27;log2&#x27;, min_samples_leaf=3,\n",
       "                      min_samples_split=7, n_estimators=99, random_state=1)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-5\" type=\"checkbox\" checked><label for=\"sk-estimator-id-5\" class=\"sk-toggleable__label sk-toggleable__label-arrow\">RandomForestRegressor</label><div class=\"sk-toggleable__content\"><pre>RandomForestRegressor(max_depth=17, max_features=&#x27;log2&#x27;, min_samples_leaf=3,\n",
       "                      min_samples_split=7, n_estimators=99, random_state=1)</pre></div></div></div></div></div>"
      ],
      "text/plain": [
       "RandomForestRegressor(max_depth=17, max_features='log2', min_samples_leaf=3,\n",
       "                      min_samples_split=7, n_estimators=99, random_state=1)"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Initialize the RandomForestRegressor model with specified hyperparameters from RandomSearchCV\n",
    "rf_model = RandomForestRegressor(max_depth=17, max_features='log2', min_samples_leaf=3, \n",
    "                                 min_samples_split=7, n_estimators=99, random_state=1)\n",
    "# Fit the RandomForestRegressor model on the training data\n",
    "rf_model.fit(X_train, y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Stock</th>\n",
       "      <th>Volatility</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>A</td>\n",
       "      <td>1.744272</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>AAL</td>\n",
       "      <td>1.926901</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>ABG</td>\n",
       "      <td>2.431983</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>ABT</td>\n",
       "      <td>0.922712</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>ACA</td>\n",
       "      <td>1.832131</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>608</th>\n",
       "      <td>ZG</td>\n",
       "      <td>3.319974</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>609</th>\n",
       "      <td>ZS</td>\n",
       "      <td>3.257073</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>610</th>\n",
       "      <td>ZTO</td>\n",
       "      <td>1.503303</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>611</th>\n",
       "      <td>ZUMZ</td>\n",
       "      <td>3.474088</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>612</th>\n",
       "      <td>ZUO</td>\n",
       "      <td>3.356551</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>613 rows × 2 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "    Stock  Volatility\n",
       "0       A    1.744272\n",
       "1     AAL    1.926901\n",
       "2     ABG    2.431983\n",
       "3     ABT    0.922712\n",
       "4     ACA    1.832131\n",
       "..    ...         ...\n",
       "608    ZG    3.319974\n",
       "609    ZS    3.257073\n",
       "610   ZTO    1.503303\n",
       "611  ZUMZ    3.474088\n",
       "612   ZUO    3.356551\n",
       "\n",
       "[613 rows x 2 columns]"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Use the trained RandomForestRegressor model to make predictions on the test set\n",
    "rf_pred_23 = rf_model.predict(X_test)\n",
    "\n",
    "# Compile the predictions into a DataFrame\n",
    "rf_pd_23 = pd.DataFrame({\n",
    "    'Stock': test_set['Stock'],\n",
    "    'Volatility': rf_pred_23\n",
    "})\n",
    "\n",
    "# Display the final prediction\n",
    "rf_pd_23"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Export the prediction result\n",
    "pd.DataFrame.to_csv(rf_pd_23, 'pred_value.csv', index=False)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
